#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include "cJSON.h"
#define SERVER_PORT 8082
#define SERVER_IPADDRESS "172.18.0.1"

#define SIZE 1024
#define ADDRESS_SIZE 100
#define TEXT_SIZE 150

typedef struct Message {
    char* sender; //发件人
    char** addresses; // 收件人
    int address_size; // 收件人个数
    char* date; // 发件时间
    char* subject; // 发件主题
} MessageInfo;

// 打印消息
void printMessage(MessageInfo message){
    printf("FROM: %s\n", message.sender);
    printf("To:\n");
    for(int i = 0; i < message.address_size; i ++){
        printf("\t%d. %s\n", i+1, message.addresses[i]);
    }
    printf("Subject: %s\n", message.subject);
    printf("Date: %s\n", message.date);  
}

// int转string
char* int2String(int number){
    char* str = (char*)malloc(sizeof(int));
    memset(str, 0, sizeof(int));
    char temp;
    int index = 0;
    while(number != 0){
        str[index ++] = number % 10 + '0';
        number /= 10;
    }
    // 反转
    for(int i = index -1; i >= index / 2; i --){
        temp = str[i];
        str[i] = str[index - i - 1];
        str[index - i - 1] = temp;
    }
    str[index] = '\0';
    return str; 
}
// 获取指定字符出现的第一个位置
int firstIndexOfChar(char* str, char c){
    for(int i = 0; str[i] != '\0'; i ++){
        if(str[i] == c){
            return i;
        }
    }
    return -1;
}
// 拼接字符串
char*  splitStrings(char* str1, char* str2){
    char* str = (char*)malloc(SIZE);    
    memset(str, 0, SIZE);
    strcat(str, str1);
    strcat(str, str2);
    return str;
}

// 截取字符串
char* subString(char* _str, int start, int end){
    char* str = (char*)malloc(SIZE);
    memset(str, 0, SIZE);
    int index = 0;
    for (int i = 0; _str[i] != '\0'; i++){
        while(_str[i] != '\0' && i >= start && i <= end){
            str[index ++] = _str[i++];
        }
    }
    str[index] = '\0';
    return str;
}

// 获取<>信息
int parseCurlyBraces(char line[], char* address){
    int i,index;
    i = index = 0;
    while(line[i] != '\0'){
        if(line[i] == '<'){
            i ++;
            while(line[i] != '>'){
                address[index ++] = line[i++];
            }
            address[index] = '\0';
            break;
        }
        i ++;
    }
    return index;
}
// 获取字符过滤信息
char* parseHeadAndTail(char line[]){
    int j, start,flag;
    j= start = flag = 0;
    while(line[j] != '\0'){
        if(line[j] == '\t'){
            start = j + 1;
            break;
        }
        while (line[j] == ' '){
            flag = 1;
            j++;
        }
        if(flag == 1 && line[j] != ' ' && line[j] != '\0'){
            start = j;
            break;  
        }
        j ++;
    }
    return subString(line, start, strlen(line) - 2);
}

// 获取地址
char* getAddress(char line[]) {
    char* address = (char*)malloc(ADDRESS_SIZE);
    memset(address, 0, ADDRESS_SIZE);
    int index = parseCurlyBraces(line, address);
    if(index == 0){
        address = parseHeadAndTail(line);
    }
    return address;
}
// 过滤消息
MessageInfo filterMessage(char* filepath){
    // 按行读取内容
    MessageInfo messageInfo;
    FILE* fp;
    char* CC = "Cc";
    char* TO = "To";
    char* SUBJECT = "Subject";
    char* FROM = "From";
    char* DATE = "Date";
    messageInfo.addresses = (char**)malloc(ADDRESS_SIZE * ADDRESS_SIZE);
    int index = 0;
    if((fp = fopen(filepath, "r")) == NULL){
        perror("file can not open");
        exit(1);
    }
    char line[SIZE];
    int flag = 0;
    while(!feof(fp))
    {
        fgets(line,SIZE,fp);
        char* start = subString(line, 0, firstIndexOfChar(line, ':') - 1);
        if (flag == 1){
            if (line[0] == '\t'){
                messageInfo.addresses[index ++] = getAddress(line);
            } else {
                flag = 0;
            }
        }
        if(flag == 0){
            // 收件人地址（To 与 Cc 合并）
            if (strcmp(start, TO) == 0 || strcmp(start, CC) == 0){
                flag = 1;
                messageInfo.addresses[index ++] = getAddress(line);
            } else if (strcmp(start, FROM) == 0){// 发件人地址
                messageInfo.sender = (char*)malloc(ADDRESS_SIZE);
                memset(messageInfo.sender, 0, ADDRESS_SIZE);
                parseCurlyBraces(line, messageInfo.sender);
            } else if (strcmp(start, SUBJECT) == 0){ // 主题
                messageInfo.subject = parseHeadAndTail(line);
            }
             else if (strcmp(start, DATE) == 0){ // 发送时间
                messageInfo.date = parseHeadAndTail(line);
            }
        }
    }
    messageInfo.address_size = index;
    fclose(fp);
    return messageInfo;
}

// 将message转为Json
char* parseMessage2Json(MessageInfo message){
     cJSON* root =  cJSON_CreateObject();
     cJSON* array =  cJSON_CreateArray();
     for(int i = 0; i < message.address_size; i ++){
        cJSON_AddItemToArray(array, cJSON_CreateString(message.addresses[i]));
     }
     cJSON_AddItemToObject(root, "sender", cJSON_CreateString(message.sender));
     cJSON_AddItemToObject(root, "addresses", array);
     cJSON_AddItemToObject(root, "date", cJSON_CreateString(message.date));
     cJSON_AddItemToObject(root, "subject", cJSON_CreateString(message.subject));
     return cJSON_Print(root);
}
// 发送UDP请求
void callUdp(MessageInfo message){
    // 打印消息
    printMessage(message);
    // 将message转换为json
    char* data = parseMessage2Json(message);
    //创建socket对象
    int sockfd=socket(AF_INET,SOCK_DGRAM,0);
    struct sockaddr_in addr;
    addr.sin_family =AF_INET;
    addr.sin_port =htons(SERVER_PORT);
    addr.sin_addr.s_addr = inet_addr(SERVER_IPADDRESS);
    // 发送消息
    int flag = sendto(sockfd, data, strlen(data), 0, (struct sockaddr*)&addr, sizeof(addr));
    printf("%d\n", flag);
    close(sockfd);
}
// 发送邮件, 并清理缓存
void sendEmail(char* cmd, char* filepath){
    // 开启一个新进程，用于发送邮件
    pid_t cpid;
    cpid = fork();
    if (cpid < 0){
        perror("fork failed");
        exit(-1);
    } else if(cpid == 0){
         // 调用发送邮件程序
        system(cmd);
        exit(0);
    } else {
        int status;
        waitpid(cpid, &status, 0);
        // 过滤消息，获取收件人地址
        MessageInfo messageInfo = filterMessage(filepath);
        // 将消息告诉收件人
        callUdp(messageInfo);
        //删除文件
        if(remove(filepath) != 0){
            perror("file remove failed");
            exit(0);
        }
    }
}

int main(void)
{
    char temp;
    FILE* fp;
    char* pid = int2String(getpid());
    char* SEND_MAIL = "/usr/sbin/sendmail -G -i -t $@ < ";
    // dev
//    char* path = "/home/ccoke/program/data/file/temp/";
    // prod
    char* path = "/home/vmail/temp/";

    char* filepath = splitStrings(path, pid);
    char* cmd = splitStrings(SEND_MAIL, filepath);
// 读取输入流，并存入缓存文件
   if((fp = fopen(filepath, "w")) == NULL){
        perror("file can not open");
        exit(1);
    }
    while((temp = getchar()) != -1){
        fputc(temp, fp);
    }
    fclose(fp);
    // 发送邮件
    sendEmail(cmd, filepath);
    return 0;
}
